/**
 * 依赖包漏洞检测弹窗
 */

import React from 'react';
import PropTypes from 'prop-types';
import { Dialog, Tag, Button, Collapse } from '@teamix/ui';
import exceed from 'utils/apimap';
import ListLoading from 'atComponents/ListLoading';
import UsersAvatar from '@alife/teamix-at-users-avatar';
import utils from 'utils';
import { navigateOpen } from 'utils/router';
import { YunxiaoIcon, Title } from '@alife/devops-ui';
import PathEllipsis from 'components/pathEllipsis';
import Content from './content';
import Description from './description';
import CreateCRModal from 'components/createCRModal/loadable';
import './index.scss';
import intl from '../../locale';

const prefix = 'dependency-single-build-detail';
const levelMap = {
  Blocker: 'red',
  Major: 'blue',
  Critical: 'orange',
  default: undefined,
};

const { organization } = window.FORCE;

export default class buildDetailDialog extends React.Component {
  static propTypes = {
    // build数据
    build: PropTypes.object,
    // 当前issue
    issue: PropTypes.object,
    onClose: PropTypes.func,
    projectId: PropTypes.number,
    updateCommitId: PropTypes.func,
  };

  static defaultProps = {
    build: {},
    issue: {},
    onClose: () => {},
    projectId: window.FORCE.pathResource ? window.FORCE.pathResource.id : null,
    closeCommitDetail: () => {},
    updateCommitId: () => {},
  };

  constructor(props) {
    super(props);
    this.dialog = React.createRef();

    this.state = {
      activityList: [],
      activeLevel: '',
      isLoadingActivity: true,
      isLoadingList: true,
      isLoadingPatch: true,
      patchInfo: null,
      repairInfo: null,
      issueDetailList: [],
      createMrModalOpen: false,
      issue_list: [],
    };
  }

  componentDidMount() {
    this.getActivity();
    this.getList();
    this.getPatch();
    // 用来获取commit_id
    this.getIssuesDetail();
  }

  onClose = () => {
    this.props.onClose();
  };

  // 获取是否有修复方案字段
  getPatch = () => {
    const { build, issue, projectId } = this.props;
    const params = {
      build_id: build.id,
      project_id: projectId,
      issue_id: issue.build_issue_id,
    };

    exceed
      .fetch({
        api: 'project.security.issue.patch',
        params,
      })
      .then((patchInfo) => {
        this.setState({
          isLoadingPatch: false,
          patchInfo,
        });
      })
      .catch((err) => {
        console.error(err);
        this.setState({
          isLoadingPatch: false,
          patchInfo: null,
        });
      });
  };

  // 获取操作记录
  getActivity = () => {
    const { build, issue } = this.props;
    exceed
      .fetch({
        api: 'projects.builds.single.activity',
        params: {
          org_id: organization.id,
        },

        data: {
          build_id: build.id,
          issue_id: issue.build_issue_id,
          issue_type: 'DEPENDENCY_ANALYSE',
        },
      })
      .then((result) => {
        const list = result.slice(1);
        this.setState({
          isLoadingActivity: false,
          activityList: list,
        });
      })
      .fail((err) => {
        console.error(err);
        this.setState({
          isLoadingActivity: false,
        });
      });
  };

  // 获取列表
  getList = () => {
    const { build, issue, projectId } = this.props;
    exceed
      .fetch({
        api: 'projects.builds.single.dependency.list',
        params: {
          project_id: projectId,
          build_id: build.id,
          parent_issue_id: issue.build_issue_id,
        },
      })
      .then((result) => {
        const list = result.slice(1);
        this.setState({
          isLoadingList: false,
          issueDetailList: list,
        });
      })
      .fail((err) => {
        console.error(err);
        this.setState({
          isLoadingList: false,
        });
      });
  };

  // 供子元素异步加载后强制更新dialog，否则会导致不出滚动条
  forceUpdateDialog = () => {
    // this.dialog.current.forceUpdate();
  };

  renderCommitId = (commitId) => {
    if (!commitId) {
      return null;
    }
    return (
      <Button
        type="primary"
        text
        style={{ margin: '0 4px', flexShrink: 0 }}
        onClick={(e) => {
          this.props.onClose();
          this.props.updateCommitId(e, commitId);
        }}
      >
        {commitId.slice(0, 8)}
      </Button>
    );
  };

  renderActivityItem = (item) => {
    const operationType = item.operation_type ? item.operation_type.toLowerCase() : '';
    const { commit_id, reason } = item.extra_info ? item.extra_info : {};
    let text = '';
    switch (operationType) {
      case 'created':
        text = intl.get({
          id: 'code-assets.components.dependencyIssueDetailDialog.ScanToFindProblems',
          defaultMessage: '扫描发现问题',
        });
        break;
      case 'resolved':
      case 'fixed':
        text = (
          <span className="detail">
            <span>{item.operator_name}</span>
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.Submitted',
              defaultMessage: '提交',
            })}
            {this.renderCommitId(commit_id)}
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.FixedTheIssue',
              defaultMessage: '修复了问题',
            })}
          </span>
        );
        break;
      case 'unresolved':
      case 'new':
        text = (
          <span className="detail">
            <span>{item.operator_name}</span>
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.Submitted',
              defaultMessage: '提交',
            })}
            {this.renderCommitId(commit_id)}
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.TheCurrentIssueIsNot',
              defaultMessage: '未解决当前问题',
            })}
          </span>
        );
        break;
      case 'ignore': {
        text = (
          <span className="detail">
            <span>{item.operator_name}</span>
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.IgnoredProblem',
              defaultMessage: '忽略了问题',
            })}
          </span>
        );
        break;
      }
      case 'open':
        text = (
          <span className="detail">
            <span>{item.operator_name}</span>
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.TheProblemIsReopenedAnd',
              defaultMessage: '重新打开了问题，扫描结果问题未解决',
            })}
          </span>
        );
        break;
      case 'close':
        text = (
          <span className="detail">
            <span>{item.operator_name}</span>
            {intl.get({
              id: 'code-assets.components.dependencyIssueDetailDialog.TheProblemWasManuallyClosed',
              defaultMessage: '手动关闭了问题，关闭原因：',
            })}
            {reason}
          </span>
        );
        break;
      default:
        text = '';
    }

    return (
      <div className={`${prefix}-history-list-item`}>
        <div className={`${prefix}-history-list-item-left`}>{text}</div>
        <div className={`${prefix}-history-list-item-right`}>
          {utils.getBeautyTime(item.gmt_create)}
        </div>
      </div>
    );
  };

  renderCountInfo = () => {
    const { issue } = this.props;
    const { activeLevel } = this.state;

    return (
      <div className={`${prefix}-detail-count`}>
        <Button
          text
          type="primary"
          style={{ marginRight: 8 }}
          className={activeLevel === '' ? '' : 'inactive'}
          onClick={() => {
            this.setState({ activeLevel: '' });
          }}
        >
          <Tag color={levelMap.default}>
            <span>
              {intl.get({
                id: 'code-assets.components.dependencyIssueDetailDialog.All',
                defaultMessage: '全部',
              })}
            </span>
            <span className="count">
              {issue.blocker_count + issue.critical_count + issue.major_count}
            </span>
          </Tag>
        </Button>
        {issue.blocker_count ? (
          <Button
            text
            type="primary"
            style={{ marginRight: 8 }}
            className={activeLevel === 'blocker' ? '' : 'inactive'}
            onClick={() => {
              this.setState({ activeLevel: 'blocker' });
            }}
          >
            <Tag color={levelMap.Blocker}>
              <span>Blocker</span>
              <span className="count">{issue.blocker_count}</span>
            </Tag>
          </Button>
        ) : null}

        {issue.critical_count ? (
          <Button
            text
            type="primary"
            style={{ marginRight: 8 }}
            className={activeLevel === 'critical' ? '' : 'inactive'}
            onClick={() => {
              this.setState({ activeLevel: 'critical' });
            }}
          >
            <Tag color={levelMap.Critical}>
              <span>Critical</span>
              <span className="count">{issue.critical_count}</span>
            </Tag>
          </Button>
        ) : null}

        {issue.major_count ? (
          <Button
            text
            type="primary"
            className={activeLevel === 'major' ? '' : 'inactive'}
            onClick={() => {
              this.setState({ activeLevel: 'major' });
            }}
          >
            <Tag color={levelMap.Major}>
              <span>Major</span>
              <span className="count">{issue.major_count}</span>
            </Tag>
          </Button>
        ) : null}
      </div>
    );
  };

  handleFooterClick = () => {
    const { patchInfo } = this.state;
    if (patchInfo.merge_request_id && patchInfo.merge_request_state !== 'closed') {
      // 前往
      navigateOpen(
        `/${window.FORCE.pathResource.fullPath}/merge_request/${patchInfo.merge_request_id}`,
      );
      return;
    }
    if (this.state.isCreatingBranch) {
      return;
    }
    this.setState({
      isCreatingBranch: true,
    });

    const { build, issue, projectId } = this.props;
    const params = {
      build_id: build.id,
      project_id: projectId,
      issue_id: issue.build_issue_id,
    };

    exceed
      .fetch({
        api: 'project.security.issue.repair',
        params,
      })
      .then((repairInfo) => {
        this.setState({
          isCreatingBranch: false,
          repairInfo,
        });
      })
      .fail(() => {
        this.setState({
          isCreatingBranch: false,
        });
      });
    this.setState({
      createMrModalOpen: true,
    });
  };

  // 转化成通用格式
  commonFile = () => {
    const { issue } = this.props;
    // 转化成通用格式
    const file = {
      file_name: issue.file_name,
      issue_count_info: { blocker: 0, critical: 0, major: 0, ...{ [issue.level]: 1 } },
      issue_id_list: [issue.build_issue_id],
      build_result_id: issue.build_result_id,
    };
    return file;
  };

  getIssuesDetail() {
    const { projectId } = this.props;
    const file = this.commonFile();

    const { issue_id_list } = file;

    const buildId = file.build_result_id;

    exceed
      .fetch({
        api: 'projects.builds.issues.batch',
        params: { projectId: projectId || window.FORCE.pathResource.id, buildId },
        data: {
          issue_ids: issue_id_list.join(','),
        },
      })
      .then((result) => {
        result.shift();

        this.setState({
          issue_list: result,
        });
      })
      .fail(console.log);
  }

  getCreateCommitId = (activityList) => {
    // 获取引入的记录
    const createdActivity = activityList.find(
      (item) => item.operation_type && item.operation_type.toLowerCase() === 'created',
    );
    let createCommitId =
      (createdActivity && createdActivity.extra_info && createdActivity.extra_info.commit_id) || '';

    if (!createCommitId) {
      createCommitId = this.state.issue_list[0] ? this.state.issue_list[0].intro_commit : '';
    }
    return createCommitId;
  };

  render() {
    const { build, issue, projectId } = this.props;
    const {
      isLoadingActivity,
      activityList,
      activeLevel,
      isLoadingList,
      issueDetailList,
      isLoadingPatch,
      patchInfo,
      repairInfo,
      createMrModalOpen,
      isCreatingBranch,
    } = this.state;

    // 当前状态
    const status = issue.status.toLowerCase();

    const createCommitId = this.getCreateCommitId(activityList);

    const curIssueDetailList = issueDetailList.filter((item) => {
      return !activeLevel || item.level.toLowerCase() === activeLevel;
    });

    const title = (
      <Title trigger={<span className="title-file-name">{issue.title}</span>} align="t">
        <span>{issue.title}</span>
      </Title>
    );

    return (
      <React.Fragment>
        <Dialog
          title={
            <div className="dependency-title">
              <span className={`dependency-${status}`}>
                {status === 'unresolved' || status === 'new'
                  ? intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.NotResolved',
                      defaultMessage: '未解决',
                    })
                  : intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.Resolved',
                      defaultMessage: '已解决',
                    })}
              </span>
              {title}
            </div>
          }
          visible
          className="dependency-issue-detail-dialog"
          style={{ width: 920 }}
          onCancel={this.onClose}
          onClose={this.onClose}
          footer={
            !isLoadingPatch && patchInfo ? (
              <Button type="primary" loading={isCreatingBranch} onClick={this.handleFooterClick}>
                {patchInfo.merge_request_id && patchInfo.merge_request_state !== 'closed'
                  ? intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.GoToTheMergeRequest',
                      defaultMessage: '前往合并请求完成修复',
                    })
                  : intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.AutomaticallyFixedMergeRequests',
                      defaultMessage: '创建合并请求自动修复',
                    })}
              </Button>
            ) : (
              false
            )
          }
          isFullScreen
          id="dependency-build-detail-dialog"
          ref={this.dialog}
        >
          <div>
            {isLoadingActivity || isLoadingList ? (
              <ListLoading />
            ) : (
              <div className={prefix}>
                {(status === 'unresolved' || status === 'new') && issue.suggestion && (
                  <div className={`${prefix}-suggestion`}>
                    <div className={`${prefix}-suggestion-icon`}>
                      <YunxiaoIcon type="resource-pool-line" />
                    </div>
                    <div className={`${prefix}-suggestion-content`}>
                      <div className="title">
                        {intl.get({
                          id: 'code-assets.components.dependencyIssueDetailDialog.RecommendedSolutions',
                          defaultMessage: '推荐修复方案',
                        })}
                      </div>
                      <div className="suggestion">{issue.suggestion}</div>
                    </div>
                  </div>
                )}

                <div className={`${prefix}-info`}>
                  <div className={`${prefix}-info-left`}>
                    <div className={`${prefix}-info-left-top`}>
                      <div className={`${prefix}-info-left-top-version`}>
                        <div className="title">
                          {intl.get({
                            id: 'code-assets.components.dependencyIssueDetailDialog.ScanVersion',
                            defaultMessage: '扫描版本',
                          })}
                        </div>
                        <div className="version content ">{issue.content}</div>
                      </div>
                      <div className={`${prefix}-info-left-top-user`}>
                        <div className="title">
                          {intl.get({
                            id: 'code-assets.components.dependencyIssueDetailDialog.Introduced',
                            defaultMessage: '引入人',
                          })}
                        </div>
                        <div className="user content" style={{ paddingLeft: 5 }}>
                          <UsersAvatar
                            dataSource={[
                              {
                                id: '',
                                name: issue.owner,
                                avatarUrl: issue.avatar || '',
                              },
                            ]}
                            size="xs"
                            borderColor={'#f7f7f7'}
                          />

                          <span style={{ marginLeft: 8 }}>{issue.owner}</span>
                        </div>
                      </div>
                      <div className={`${prefix}-info-left-top-commit`}>
                        <div className="title">
                          {intl.get({
                            id: 'code-assets.components.dependencyIssueDetailDialog.ImportAndSubmit',
                            defaultMessage: '引入提交',
                          })}
                        </div>
                        <div className="commit content">
                          <YunxiaoIcon type="merge-line" className="commit-content-icon" />{' '}
                          <span style={{ marginRight: 20, marginLeft: 4 }}>{build.branch}</span>
                          {this.renderCommitId(createCommitId)}
                        </div>
                      </div>
                    </div>
                    <div
                      className={`${prefix}-info-left-bottom ${
                        issue.parent_issue_title ? 'has-border-bottom' : ''
                      }`}
                    >
                      {/* <div className={`${prefix}-info-left-bottom-language`}>
                       <div className="title">语言</div>
                       <div className="language content">
                         <a href={issue.cve_url} target="_blank">{issue.cve_id}</a>
                       </div>
                      </div> */}
                      <div className={`${prefix}-info-left-bottom-file`}>
                        <div className="title">
                          {intl.get({
                            id: 'code-assets.components.dependencyIssueDetailDialog.File',
                            defaultMessage: '所属文件',
                          })}
                        </div>
                        <div className="file-name content">
                          {
                            // 这个路径禁止跳转规则：这个路径禁止跳转规则：1. 包含jar 2. 包含INF
                            issue.file_name.includes('jar') || issue.file_name.includes('INF') ? (
                              <PathEllipsis path={issue.file_name} />
                            ) : (
                              <Button
                                type="primary"
                                text
                                component="a"
                                target="_blank"
                                href={`/${window.FORCE.pathResource.fullPath}/blob/${createCommitId}/${issue.file_name}`}
                              >
                                <PathEllipsis path={issue.file_name} />
                              </Button>
                            )
                          }
                        </div>
                      </div>
                    </div>
                    {issue.parent_issue_title && (
                      <div className={`${prefix}-info-left-bottom`}>
                        <div className={`${prefix}-info-left-bottom-file`}>
                          <div className="title">
                            {intl.get({
                              id: 'code-assets.components.dependencyIssueDetailDialog.Dependencies',
                              defaultMessage: '依赖关系',
                            })}
                          </div>
                          <div className="file-name content">
                            {intl.get(
                              {
                                id: 'code-assets.components.dependencyIssueDetailDialog.NonDirectDependencyIntroducedBy',
                                defaultMessage: '非直接依赖，由依赖 {issueParentIssue} 引入',
                              },
                              { issueParentIssue: issue.parent_issue_title },
                            )}
                          </div>
                        </div>
                      </div>
                    )}
                  </div>
                </div>
                <div className={`${prefix}-detail`}>
                  <div className={`${prefix}-detail-title`}>
                    {intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.ProblemDescription',
                      defaultMessage: '问题描述',
                    })}
                  </div>
                  {this.renderCountInfo()}
                  <div className={`${prefix}-detail-list`}>
                    <Collapse>
                      {curIssueDetailList.map((item) => {
                        return (
                          <Collapse.Panel
                            title={item.title}
                            className={item.level ? item.level.toLowerCase() : ''}
                          >
                            <div className={`${prefix}-detail-list-content`}>
                              <div className={`${prefix}-detail-list-item`}>
                                <div className="content-left">
                                  {intl.get({
                                    id: 'code-assets.components.dependencyIssueDetailDialog.Number',
                                    defaultMessage: '编号',
                                  })}
                                </div>
                                <div className="content-right number">
                                  <a href={item.cve_url} target="_blank" rel="noreferrer">
                                    {item.cve_id}
                                  </a>
                                </div>
                              </div>
                              <div className={`${prefix}-detail-list-item`}>
                                <div className="content-left">
                                  {intl.get({
                                    id: 'code-assets.components.dependencyIssueDetailDialog.Description',
                                    defaultMessage: '描述',
                                  })}
                                </div>
                                <div className="content-right">
                                  <Description description={item.description} />
                                </div>
                              </div>
                              <div className={`${prefix}-detail-list-item`}>
                                <div className="content-left">
                                  {intl.get({
                                    id: 'code-assets.components.dependencyIssueDetailDialog.ImpactRange',
                                    defaultMessage: '影响范围',
                                  })}
                                </div>
                                <div className="content-right">
                                  <Content content={item.content} />
                                </div>
                              </div>
                            </div>
                          </Collapse.Panel>
                        );
                      })}
                    </Collapse>
                  </div>
                </div>
                <div className={`${prefix}-history`}>
                  <div className={`${prefix}-history-title`}>
                    {intl.get({
                      id: 'code-assets.components.dependencyIssueDetailDialog.IssueDynamics',
                      defaultMessage: '问题动态',
                    })}
                  </div>
                  <div className={`${prefix}-history-list`}>
                    {activityList.map((item) => {
                      return this.renderActivityItem(item);
                    })}
                  </div>
                </div>
              </div>
            )}
          </div>
        </Dialog>
        {createMrModalOpen && repairInfo && (
          <CreateCRModal
            cannotChangeProject
            isModalOpen={createMrModalOpen}
            defaultProjectId={projectId || window.FORCE.pathResource.id}
            defaultSourceBranch={repairInfo.source_branch}
            defaultTargetBranch={repairInfo.target_branch}
            extraRequestData={{
              build_patch_id: repairInfo.build_patch_id,
            }}
            title={repairInfo.title}
            desc={repairInfo.description}
            onCloseModal={() => {
              this.setState({
                createMrModalOpen: false,
              });
            }}
          />
        )}
      </React.Fragment>
    );
  }
}
